﻿using System;

using System.Collections.Generic;
using System.Text;

namespace gpsmid_wince.util {
	abstract class Tile {

		public const sbyte TYPE_MAP = 1;
		public const sbyte TYPE_CONTAINER = 2;
		public const sbyte TYPE_FILETILE = 4;
		public const sbyte TYPE_EMPTY = 3;
		public const sbyte TYPE_ROUTEDATA = 5;
		public const sbyte TYPE_ROUTECONTAINER = 6;
		public const sbyte TYPE_ROUTEFILE = 7;
		public const sbyte TYPE_WAYPOINT = 8;

		public const int OPT_WAIT_FOR_LOAD = 1;
		public const int OPT_PAINT = 2;
		public const int OPT_FIND_DEST = 4;
		public const int OPT_FIND_CURRENT = 8;
		public const int OPT_CONNECTIONS2WAY = 16;
		public const int OPT_CONNECTIONS2AREA = 32;
		public const int OPT_HIGHLIGHT = 64;

		public const sbyte LAYER_AREA = -128; //10000000 binary
		public const sbyte LAYER_ALL = (sbyte)0x40; //01000000 binary
		public const sbyte LAYER_HIGHLIGHT = (sbyte)0x20; //00100000 binary
		public const sbyte LAYER_NODE = sbyte.MaxValue;

		public float minLat;
		public float maxLat;
		public float minLon;
		public float maxLon;
		public float centerLat;
		public float centerLon;

		public short fileId = 0;
		public sbyte lastUse = 0;

		/**
		 * Paint all elements of a tile to the PaintContext that are in layer
		 * There are two special layers LAYER_AREA and LAYER_NODE
		 * @param pc
		 */
		public abstract void paint(PaintContext pc, sbyte layer);
		public abstract void walk(PaintContext pc, int opt);
		

		public abstract bool cleanup(int level);
		
		internal bool contain(PaintContext pc) {
			return pc.p.isOnScreen(minLat, minLon, maxLat, maxLon);
			/*float[] rect = new float[4];
			pc.p.screenInReal(rect);
			if (minLat > rect[2] || maxLat < rect[0])return false;
			if (minLon > rect[3] || maxLon < rect[1])return false;
			return true;*/
		}

		internal bool contain(float lat, float lon) {
			if (maxLat < lat) return false;
			if (maxLon < lon) return false;
			if (minLat > lat) return false;
			if (minLon > lon) return false;
			return true;
		}

		internal bool contain(float lat, float lon, float epsilon) {
			if ((maxLat + epsilon) < lat) return false;
			if ((maxLon + epsilon) < lon) return false;
			if ((minLat - epsilon) > lat) return false;
			if ((minLon - epsilon) > lon) return false;
			return true;
		}
/*
		bool contain(PositionMark pm) {
			if (maxLat < pm.lat) {
				return false;
			}
			if (maxLon < pm.lon) {
				return false;
			}
			if (minLat > pm.lat) {
				return false;
			}
			if (minLon > pm.lon) {
				return false;
			}
			return true;
		}
*/
		/*
		public void getCenter(Node center) {
			center.radlat = (maxLat + minLat) / 2;
			center.radlon = (maxLon + minLon) / 2;
		}

		protected void drawBounds(PaintContext pc, int r, int g, int b) {
			pc.g.setColor(r, g, b);
			IntPoint p1 = new IntPoint(0, 0);
			IntPoint p2 = new IntPoint(0, 0);
			IntPoint p3 = new IntPoint(0, 0);
			IntPoint p4 = new IntPoint(0, 0);
			Projection p = pc.getP();
			p.forward(minLat, minLon, p1);
			p.forward(minLat, maxLon, p2);
			p.forward(maxLat, maxLon, p3);
			p.forward(maxLat, minLon, p4);
			pc.g.drawLine(p1.x, p1.y, p2.x, p2.y);
			pc.g.drawLine(p2.x, p2.y, p3.x, p3.y);
			pc.g.drawLine(p3.x, p3.y, p4.x, p4.y);
			pc.g.drawLine(p4.x, p4.y, p1.x, p1.y);
			//		logger.debug("draw bounds" );
			//			System.out.println(this);
			//			System.out.println(p1.x + "," + p1.y + "/" + p2.x + "," + p2.y);
			//			pc.g.fillTriangle(p1.x, p1.y, p2.x, p2.y, p1.x, p2.y);
		}
*/
		public string toString() {
			return "Tile " + this.GetType() + " " + minLat + "," + minLon +
				"/" + maxLat + "," + maxLon;
		}
	}
}
